package com.jeeplus.test.jlnu.mailingInfo.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeeplus.file.config.FileProperties;
import com.jeeplus.file.repository.AccessoryRepository;
import com.jeeplus.test.jlnu.admissionInfo.domain.entity.AdmissionInfo;
import com.jeeplus.test.jlnu.admissionInfo.mapper.ExcelMapper;
import com.jeeplus.test.jlnu.archivalInfo.domain.entity.ArchParmerter;
import com.jeeplus.test.jlnu.mailingInfo.domain.entity.MailingInfo;
import com.jeeplus.test.jlnu.mailingInfo.domain.vo.MailingInfoVo;
import com.jeeplus.test.jlnu.mailingInfo.mapper.MailingInfoMapper;
import com.jeeplus.test.jlnu.mailingInfo.service.MailingInfoService;
import com.jeeplus.test.website.websiteFile.domain.vo.WebsiteFileReqVo;
import com.jeeplus.test.website.websiteFile.domain.vo.WebsiteFileRespVo;
import com.jeeplus.test.website.websiteFile.service.WebsiteFileService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MailingInfoServiceImpl extends ServiceImpl<MailingInfoMapper, MailingInfo> implements MailingInfoService {


    @Autowired
    private MailingInfoMapper mailingInfoMapper;

    @Autowired
    private ExcelMapper excelMapper;

    @Autowired
    private WebsiteFileService websiteFileService;  // 复用现有文件服务

    @Autowired
    private AccessoryRepository accessoryRepository;  // 已有文件存储工具

    @Autowired
    private FileProperties fileProperties;  // 文件配置（获取允许的文件类型）

    @Value("${config.accessory.minIO.endpoint}")
    private String systemMac;  // MinIO访问地址

    private static final String FILE_SERVER = "file";  // 文件服务前缀（与WebsiteFile保持一致）



    @Override
    public Page<MailingInfo> getMailingInfoPage(ArchParmerter mailingInfoReqVo, Page<MailingInfo> page) {
        // 1. 获取分页结果和字段配置信息
        Page<MailingInfo> mailingInfoPage = mailingInfoMapper.getMailingInfoPage(mailingInfoReqVo, page);


        return mailingInfoPage;
    }

    @Override
    public int updateByStuid(MailingInfo mailingInfo) {
        int i = mailingInfoMapper.updateByStuid(mailingInfo);
        return i;
    }

    @Override
    public int saveMail(MailingInfo mailingInfo) {
        List<AdmissionInfo> admissionInfos = new ArrayList<>();
        AdmissionInfo admissionInfo = new AdmissionInfo();
        admissionInfo.setStudentId(mailingInfo.getStudentId());
        admissionInfo.setExpectedGraduationDate(mailingInfo.getGraduationDate());
        admissionInfos.add(admissionInfo);
        mailingInfoMapper.saveAdmission(mailingInfo);
        // 插入学籍信息表（只插入学号）
        excelMapper.saveSecondData(admissionInfos);
        // 插入毕业信息表（只插入学号）
//        excelMapper.saveThirdData(admissionInfos);
        // 插入就业信息表（只插入学号）
        excelMapper.saveFourth(admissionInfos);
        // 插入学位信息表（只插入学号）
        excelMapper.saveFifth(admissionInfos);
        // 插入学历信息表（只插入学号）
        excelMapper.saveSixth(admissionInfos);
//        excelMapper.saveEighth(admissionInfos);

//        excelMapper.saveEighth(admissionInfos);
        excelMapper.saveFourteenth(admissionInfos);
        excelMapper.saveFifteenth(admissionInfos);
        // 创建两个列表来存储不同 flag 的对象
        List<AdmissionInfo> flagOneList = new ArrayList<>();
        List<AdmissionInfo> otherFlagList = new ArrayList<>();

        for (AdmissionInfo admissionInfoss : admissionInfos) {
            if ("1".equals(admissionInfoss.getFlag())) {
                flagOneList.add(admissionInfoss);
            } else {
                otherFlagList.add(admissionInfoss);
            }
        }

        // 对于 flag 为 1 的对象调用保存方法
        if (!flagOneList.isEmpty()) {
            excelMapper.saveNinth(flagOneList);
            excelMapper.saveTenth(flagOneList);
            excelMapper.saveEleth(flagOneList);
            excelMapper.saveThirteenth(flagOneList);
        }

        // 对于 flag 为 2 或其他的对象调用保存方法
        if (!otherFlagList.isEmpty()) {
            excelMapper.saveTwelfth(otherFlagList);
            excelMapper.saveSixteenth(otherFlagList);
            excelMapper.saveSeventeenth(otherFlagList);
            excelMapper.saveEighteenth(otherFlagList);
        }
       return mailingInfoMapper.saveMail(mailingInfo);
    }

    @Override
    public int checkStudentId(String studentId) {
        return mailingInfoMapper.checkStudentId(studentId);
    }


    @Override
    public void insertDataMailingInfo(List<MailingInfoVo> dataList){
        mailingInfoMapper.insertDataMailingInfo(dataList);
    }
//    @Override
//    public boolean saveOrUpdateMailing(MailingInfo mailingInfo, MultipartFile file) {
//        // 仅处理新文件上传（不删除旧文件）
//        if (file != null && !file.isEmpty()) {
//            String newFileId = uploadFileToWebsiteFile(file);
//            mailingInfo.setMinioId(newFileId);  // 关联新文件ID（覆盖旧ID）
//        }
//
//        // 保存或更新邮寄信息
//        return super.saveOrUpdate(mailingInfo);
//    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean attachment(String id, MultipartFile file) {
        MailingInfo mailingInfo = this.getById(id);
        if (mailingInfo == null) {
            return false;
        }

        String fileId = uploadFileToWebsiteFile(file);
        if (fileId == null) {
            return false;
        }

        MailingInfo updateEntity = new MailingInfo();
        updateEntity.setId(id);
        updateEntity.setMinioId(fileId);
        return this.updateById(updateEntity);
    }

    @Override
    public Map<String, Object> getFileByMailingId(String id) {
        // 1. 查询邮寄信息，获取关联的文件ID
        MailingInfo mailingInfo = this.getById(id);
        if (mailingInfo == null) {
            throw new RuntimeException("邮寄信息不存在：" + id);
        }
        String fileId = mailingInfo.getMinioId();
        if (fileId == null || fileId.isEmpty()) {
            throw new RuntimeException("该记录未关联任何文件");
        }

        // 2. 查询文件记录
        WebsiteFileRespVo fileResp = websiteFileService.queryById(fileId);
        if (fileResp == null) {
            throw new RuntimeException("文件记录不存在：" + fileId);
        }

        try {
            // 3. 从bucketName和fileName构建文件路径
            String bucketName = fileResp.getBucketName();
            String fileName = fileResp.getFileName();

            if (bucketName == null || bucketName.trim().isEmpty()) {
                throw new RuntimeException("文件路径前缀为空");
            }
            if (fileName == null || fileName.trim().isEmpty()) {
                throw new RuntimeException("文件名为空");
            }

            String minioPath = bucketName.trim()
                    .replaceFirst("^/file", "")  // 移除开头的/file
                    .replaceAll("/+", "/");       // 合并多个斜杠

            if (!minioPath.endsWith("/")) {
                minioPath += "/";
            }

            String fullPath = minioPath + fileName.trim();
            fullPath = fullPath.replaceAll("/+", "/");

            int lastSlashIndex = fullPath.lastIndexOf("/");
            String path = lastSlashIndex > 0 ? fullPath.substring(0, lastSlashIndex) : "";
            String actualFileName = fullPath.substring(lastSlashIndex + 1);

            File minioFile = accessoryRepository.get(path, actualFileName);
            if (minioFile == null || !minioFile.exists()) {
                throw new RuntimeException("文件不存在：" + fullPath);
            }

            byte[] fileBytes = Files.readAllBytes(minioFile.toPath());

            Map<String, Object> result = new HashMap<>(2);
            result.put("fileBytes", fileBytes);
            result.put("fileName", fileName);
            return result;
        } catch (Exception e) {
            throw new RuntimeException("文件读取失败：" + e.getMessage());
        }
    }
    @Override
    public WebsiteFileReqVo getFileInfoByMailingId(String id) {
        MailingInfo mailingInfo = this.getById(id);
        if (mailingInfo == null) {
            return null;
        }

        String fileId = mailingInfo.getMinioId();
        if (fileId == null || fileId.trim().isEmpty()) {
            return null;
        }

        WebsiteFileRespVo fileResp = websiteFileService.queryById(fileId);
        if (fileResp == null) {
            return null;
        }

        WebsiteFileReqVo websiteFileReqVo = new WebsiteFileReqVo();
        websiteFileReqVo.setFileName(fileResp.getFileName());
        websiteFileReqVo.setFileUrl(fileResp.getFileUrl());
        return websiteFileReqVo;
    }


    private String uploadFileToWebsiteFile(MultipartFile file) {
        try {
            String originalFileName = file.getOriginalFilename();
            if (originalFileName == null || originalFileName.isEmpty()) {
                throw new RuntimeException("文件名不能为空");
            }
            int lastDotIndex = originalFileName.lastIndexOf(".");
            String fileNameWithoutExt = originalFileName;
            String ext = "";
            if (lastDotIndex > 0) {
                fileNameWithoutExt = originalFileName.substring(0, lastDotIndex);
                ext = originalFileName.substring(lastDotIndex);
            }
            String timestamp = String.valueOf(System.currentTimeMillis());
            String newFileName = fileNameWithoutExt + "_" + timestamp + ext;

            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH) + 1;
            String minioPath = "/test/" + year + "/" + month + "/";
            String uploadPath = "/file" + minioPath;

            if (!fileProperties.isAvailable(originalFileName)) {
                throw new RuntimeException("不支持的文件类型：" + originalFileName);
            }

            accessoryRepository.save(file, minioPath, newFileName);

            WebsiteFileReqVo fileReq = new WebsiteFileReqVo();
            fileReq.setId("WB" + IdUtil.simpleUUID());
            fileReq.setFileName(newFileName);
            fileReq.setFileUrl(systemMac + uploadPath + newFileName);
            fileReq.setBucketName(uploadPath);
            fileReq.setBucketId(FILE_SERVER);
            fileReq.setSize("");
            fileReq.setOrganizedName("");
            fileReq.setIconFlag("");
            fileReq.setIcon("");

            if (!websiteFileService.addContent(fileReq)) {
                throw new RuntimeException("文件记录保存失败");
            }
            return fileReq.getId();
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return null;
        }
    }



    @Override
    public MailingInfoVo selectMailingById(Long id){
        return baseMapper.selectMailingById(id);
    }
    private void copyNonNullProperties(Object source,Object target){
        if(source == null || target == null){
            return;
        }
        Field[] sourceFields = source.getClass().getDeclaredFields();
        for(Field sourceField : sourceFields){
            if("ids".equals(sourceField.getName())){
                continue;
            }
            try{
                sourceField.setAccessible(true);
                Object value = sourceField.get(source);
                if (value != null){
                    Field targetField = ReflectionUtils.findField(target.getClass(),sourceField.getName());
                    if(targetField != null){
                        targetField.setAccessible(true);
                        targetField.set(target,value);
                    }
                }
            }catch (IllegalArgumentException | IllegalAccessException e){
                log.warn("复制属性时发生异常: {}");
            }
        }
    }
    @Override
    public boolean batchUpdate(MailingInfoVo mailingInfoVo){
        if(mailingInfoVo.getIds() == null || mailingInfoVo.getIds().trim().isEmpty()){
            throw new IllegalArgumentException("ids不能为空");
        }
        List<Long> idList = Arrays.stream(mailingInfoVo.getIds().split(",")).map(idStr ->{
            try{
                return Long.parseLong(idStr.trim());
            } catch (NumberFormatException e){
                throw new IllegalArgumentException("ids格式不正确: " + idStr);
            }
        }).collect(Collectors.toList());
        UpdateWrapper<MailingInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id",idList);
        MailingInfo entity = new MailingInfo();
        copyNonNullProperties(mailingInfoVo, entity);
        return update(entity,updateWrapper);
    }
    @Override
    public boolean saveOrUpdateMailing(MailingInfo mailingInfo) {
        return super.saveOrUpdate(mailingInfo);
    }
    @Override
    public Page<MailingInfo> selectAllMailingVOs(MailingInfoVo mailingInfoVo,Page<MailingInfo> page){
        if (StringUtils.isNotEmpty(mailingInfoVo.getApprovalStatus())) {
            String[] arr = mailingInfoVo.getApprovalStatus().split(",");
            List<String> list = Arrays.asList(arr);
            mailingInfoVo.setApproveStateList(list);
        }
        Page<MailingInfo> qualificationInfoPage = mailingInfoMapper.selectAllMailingVOs(mailingInfoVo,page);
        return qualificationInfoPage;

    }
    @Override
    public ResponseEntity<byte[]> DataDowload(List<String> ids) {
        List<MailingInfo> mailingInfos = mailingInfoMapper.selectBatchIds(ids);

        if (mailingInfos == null || mailingInfos.isEmpty()) {
            return ResponseEntity.noContent().build();
        }


        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            EasyExcel.write(outputStream, MailingInfoVo.class)
                    .sheet("转递信息")
                    .doWrite(mailingInfos);

            HttpHeaders headers = new HttpHeaders();
            String fileName = "mailing" + System.currentTimeMillis() + ".xlsx";
            headers.add("Content-Disposition", "attachment; filename=\"" +
                    URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()) + "\"");
            headers.add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(outputStream.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException("导出Excel失败：" + e.getMessage(), e);
        }
    }

    @Override
    public int batchUpdateMailing(MailingInfoVo mailingInfoVo) {
        return mailingInfoMapper.batchUpdateMailing(mailingInfoVo.getAdmissionInfoList(),mailingInfoVo.getTransferState());
    }
}
